
/* <primitive: 70>
 * <Behavior> basicNew
 * Instantiate the receiver.  Had better not be a variable-sized class.
 * Essential.
 */
void primNew()
{
	int klass;
	//BOGUS, enforce class is fixed fields

	klass = peek(0);
	popNandPush( 1, instantiate(klass) );
}

/* <primitive: 71>
 * <Behavior> basicNew: <SmallInt>
 * Instantiate the receiver.  Had better be a variable-sized class.
 * Essential.
 */
void primNewN()
{
	int i, c;
	
	//BOGUS, enforce class is indexable
	
	c = peek(1);
	i = unpackSmInt(peek(0));
	
	if(!success) return;
	
	popNandPush( 2 , instantiateN(c,i) );
}

/* <primitive: 73>
 * <Object> instVarAt: <SmallInteger>
 * Operates on fixed fields.
 * Essential.
 */
void primInstVarAt()
{
	int i,o,fmt,v,f,namedSize,s,nWords,nBytes;
	
	o = peek(1);
	i = unpackSmInt(peek(0));
	
	if(!success) return;
	
	fmt = formatOf(o);

	if(fmt == 0 || fmt == 1){ //no fields or named pointed
		if( i>=1 && i<=sizeOf(o) )
			popNandPush(2, slotOf(o,i) );
		else
			success=0;
	}else if(fmt == 2){ //indexed pointers => fail
		success=0;
	}else if(fmt == 3){ //named and indexed pointers
		namedSize = instSizeOf(o);
		if( i>=1 && i<=namedSize )
			popNandPush(2, slotOf(o,i) );
		else
			success=0;
	}else if(fmt == 6){ //indexed words => fail
		success=0;
	}else if(fmt >= 8 && fmt <= 11){ //indexed bytes => fail
		success=0;
	}else{
		PANIC("other instVarAt:");
	}
}

/* <primitive: 74>
 * <Object> instVarAt: <SmallInteger> put: <Object>
 * Operates on fixed fields.
 * Essential.
 */
void primInstVarAtPut()
{
	int i,o,fmt,v,f,namedSize,s,nWords,nBytes;
	
	o = peek(2);
	i = unpackSmInt(peek(1));
	v = peek(0);
	
	if(!success)return;
	
	fmt = formatOf(o);
	
	if(fmt == 0 || fmt == 1){ //no fields or named pointed
		if( i>=1 && i<=sizeOf(o) )
		{
			setSlotOf(o,i,v);
			popNandPush(3, v);
		}
		else
			success=0;
	}else if(fmt == 2){ //indexed pointers => fail
		success=0;
	}else if(fmt == 3){ //named and indexed pointers
		namedSize = instSizeOf(o);
		if( i>=1 && i<=namedSize )
		{
			setSlotOf(o,i,v);
			popNandPush(3, v);
		}
		else
			success=0;
	}else if(fmt == 6){ //indexed words => fail
		success=0;
	}else if(fmt >= 8 && fmt <= 11){ //indexed bytes => fail
		success=0;
	}else{
		PANIC("other instVarAt:");
	}
}

/* <primitive: 75>
 * <Object> hash
 * Return the identity hash of the receiver.  Fail if the reciever is a SmallInteger.
 * Essential.
 */
void primHash()
{
	if( isSmInt(peek(0)) ) success=0;
	else
	{
		int hash = packSmInt( hashOf(peek(0)) );
		popNandPush(1, hash);
	}
}

/* <primitive: 77>
 * <Behavior> someInstance
 * Answer the first instance of the reciever on the heap.  Fail if no instances.  Fail if class is SmallInteger.
 * Essential.
 */
void primSomeInstance()
{
	int klass = top();
	
	if(klass==SmallInteger){
		success=0;
		return;
	}
	
	int object = firstObject();
	
	while( object != 0 )
	{
		if( classOf(object)==klass ) {
			popNandPush(1, object);
			return;
		}
		
		object = objectAfter(object);
	}
	//end of heap with no hits :(
	success=0;
}

//76
void primStoreStackp()
{
	int cntx = peek(1);
	int newSP = peek(0);
	
	if( !isSmInt(newSP) ) success=0;
	//BOGUS also check number is non-neg and less than context size
	
	if(success)
	{
		int oldSP = slotOf(cntx, 3);
		
		if(oldSP==nil) 
			oldSP = 0;
		else
			oldSP = unpackSmInt(oldSP);
			
		//BOGUS
		
		int size = sizeOf(cntx);
		
		for(int i=oldSP + 1 + 6; i<size; i++)
			setSlotOf(cntx, i, nil);
			
		setSlotOf(cntx, 3, newSP);
		
		popNandPush(2, cntx);
	}
}

/* <primitive: 78>
 * <Object> nextInstance
 * Answer the first instance of the class of the reciever after the reciever on the heap.  Fail if no more instances.  Fail if rcvr is a SmallInteger.
 * Essential.
 */
void primNextInstance()
{
	int previousObject = top();
	int klass = classOf(previousObject);
	
	if(klass==SmallInteger){
		success=0;
		return;
	}
	
	int object = objectAfter(previousObject);
	
	while( object != 0 )
	{
		if( classOf(object)==klass ) {
			popNandPush(1, object);
			return;
		}
		
		object = objectAfter(object);
	}
	//end of heap with no hits :(
	success=0;
}

/* <primitive: 79>
 * <CompiledMethod class> newMethod: numberOfBytes <SmallInteger> header: headerWord <SmallInteger>
 * 
 * Essential.
 */
void primNewMethod()
{
	//BOGUS , missing many ways this can fail
	PANIC("newMethod");
	
	int nBytes,nWords,i,o,header,fmt,nLiterals;
	
	int CompiledMethod = peek(2);
	
	header = peek(0);
	nLiterals = ((header>>10)&255)+1;
	nBytes = unpackSmInt(peek(1));
	nWords = (nBytes+3)/4 + nLiterals; //I think numberOfBytes excludes space needed for header and literals
		
	o = allocate( nWords + 3 );
	*(int*)o = ( (nWords+1)<<2 ) | 0;
	o+=4;
	*(int*)o = CompiledMethod | 0;
	o+=4;
	switch(nBytes%4){
		case 1: fmt = 12+3; break;
		case 2: fmt = 12+2; break;
		case 3: fmt = 12+1; break;
		case 0: fmt = 12+0; break;
	}
	*(int*)o = (fmt<<8) | (0<<2) | 0;
	
	for(i = 1; i <= nBytes; i++) setByteSlotOf(o,i,0);
	for(i = 1; i <= nLiterals; i++) setSlotOf(o,i,nil);
	setSlotOf(o,1,header);
	
	popNandPush(3, o);
}
